package org.uim.cricket.analyzer.report;

import java.util.List;

import org.apache.commons.lang3.StringEscapeUtils;
import org.uim.cricket.entities.Player;
import org.uim.cricket.entities.aggr.SingleInning;
import org.uim.cricket.entities.batting.BattingInning;
import org.uim.cricket.entities.bowling.BowlingInning;
import org.uim.cricket.entities.inning.InningExtras;
import org.uim.cricket.entities.partnerships.FallOfWicket;

public class XMLInningReporting {

	private StringBuilder xml = new StringBuilder();	
    private boolean battingOutput = true;
    private boolean bowlingOutput = true;
	private boolean fallOfWicketOutput = true;
	
	public XMLInningReporting(boolean isBatOutput, boolean isBowlOutput, boolean isFallOfWktOutput) {
		this.battingOutput = isBatOutput;
		this.bowlingOutput = isBowlOutput;
		this.fallOfWicketOutput = isFallOfWktOutput;
	}
	
    public StringBuilder appendSingleInning(SingleInning inn, int indent) throws Exception {
    	this.xml = new StringBuilder();
    	
    	this.appendXMLLineIndent(xml, indent);
        xml.append("<Inning");
        xml.append(this.appendXMLAttrib("id", inn.getInningMatch(), false));
        if (inn.getTargetChased() > 0) {
            xml.append(this.appendXMLAttrib("target", inn.getTargetChased(), false));
            if (inn.getTargetChasedOvers() != null) {
                xml.append(this.appendXMLAttrib("targetOvers", inn.getTargetChasedOvers(), false));
            }
        }
        xml.append(">\n");

        if (inn.getTotals() != null) {
            this.appendXMLLineIndent(xml, indent + 1);
            xml.append("<Total");
            xml.append(this.appendXMLAttrib("runs", inn.getTotals().getRuns(), false));
            xml.append(this.appendXMLAttrib("overs", inn.getTotals().getOvers(), false));
            xml.append(this.appendXMLAttrib("wickets", inn.getTotals().getWickets(), false));
            if (inn.getTotals().getMinutes() > 0) {
                xml.append(this.appendXMLAttrib("mins", inn.getTotals().getMinutes(), false));
            }
            if (inn.getTotals().isDeclared()) {
                xml.append(this.appendXMLAttrib("declared", inn.getTotals().isDeclared(), false));
            }
            xml.append(" />\n");
        }
        if (inn.getExtras() != null) {
            InningExtras extras = inn.getExtras();
            
            this.appendXMLLineIndent(xml, indent + 1);
            xml.append("<Extras");
            if (extras.getBies() > 0) {
                xml.append(this.appendXMLAttrib("bies", extras.getBies(), false));
            }
            if (extras.getLegBies() > 0) {
                xml.append(this.appendXMLAttrib("legbies", extras.getLegBies(), false));
            }
            if (extras.getNoBalls() > 0) {
                xml.append(this.appendXMLAttrib("noballs", extras.getNoBalls(), false));
            }
            if (extras.getWides() > 0) {
                xml.append(this.appendXMLAttrib("wides", extras.getWides(), false));
            }
            if (extras.getPanelties() > 0) {
                xml.append(this.appendXMLAttrib("penalties", extras.getPanelties(), false));
            }
            if (extras.getOthers() > 0) {
                xml.append(this.appendXMLAttrib("others", extras.getOthers(), false));
            }
            xml.append(" />\n");
        }

        if (this.battingOutput) {
        	
        	this.appendXMLLineIndent(xml, indent + 1);
            xml.append("<Battings");
            xml.append(this.appendXMLAttrib("team", inn.getBattedTeam(), true));
            xml.append(">\n");
            
            List<BattingInning> bats = inn.getBatInnings();
            if (bats != null) {
                
                for (int i = 0; i<bats.size();i++) {
                    BattingInning batinn = bats.get(i);
                    
                    this.appendXMLLineIndent(xml, indent + 2);
                    xml.append("<BatInn");
                    xml.append(this.appendXMLAttrib("id", (i+1), false)).append(">\n");
                    
                    this.appendXMLLineIndent(xml, indent + 3);
                    xml.append("<Batsman");
                    xml.append(this.appendXMLAttrib("id", batinn.getBatsman().getId(), false));
                    xml.append(this.appendXMLAttrib("name", batinn.getBatsman().getTitleName(), true));
                    xml.append(this.appendXMLAttrib("shortname", batinn.getBatsman().getShortName(), true));
                    if (batinn.getBatsman().isCaptain()) {
                        xml.append(this.appendXMLAttrib("captain", batinn.getBatsman().isCaptain(), false));
                    }
                    if (batinn.getBatsman().isWicketKeeper()) {
                        xml.append(this.appendXMLAttrib("keeper", batinn.getBatsman().isWicketKeeper(), false));
                    }
                    xml.append(" />\n");
                    
                    if (batinn.getOutDetails() != null) {
                        this.appendXMLLineIndent(xml, indent + 3);
                        xml.append("<OutDetails");
                        xml.append(this.appendXMLAttrib("type", batinn.getOutDetails().getOutType().toString(), false));
                        if (batinn.getOutDetails().getBowler() != null) {
                            xml.append(this.appendXMLAttrib("bowler", batinn.getOutDetails().getBowler().getTitleName(), true));
                        }
                        if (batinn.getOutDetails().getFielders() != null) {
                            Player[] fielders = batinn.getOutDetails().getFielders();
                            boolean[] wks = batinn.getOutDetails().getWicketKeeperFielders();
                            String fields = "";
                            for (int j=0;j<fielders.length;j++) {
                                if (j>0) fields += ",";
                                if (wks != null && wks[j]) fields += "+";
                                fields += StringEscapeUtils.escapeXml(fielders[j].getTitleName());
                            }
                            xml.append(this.appendXMLAttrib("fielders", fields, false));
                        }
                        xml.append(" />\n");
                    }
                    
                    if (batinn.getStatistics() != null) {
                        this.appendXMLLineIndent(xml, indent + 3);
                        xml.append("<Stats");
                        xml.append(this.appendXMLAttrib("runs", batinn.getStatistics().getRuns(), false));
                        xml.append(this.appendXMLAttrib("balls", batinn.getStatistics().getBalls(), false));
                        xml.append(this.appendXMLAttrib("mins", batinn.getStatistics().getMins(), false));
                        xml.append(this.appendXMLAttrib("fours", batinn.getStatistics().getFours(), false));
                        xml.append(this.appendXMLAttrib("sixes", batinn.getStatistics().getSixes(), false));
                        xml.append(" />\n");
                    }
                    
                    this.appendXMLLineIndent(xml, indent + 2);
                    xml.append("</BatInn>\n");
                }
                
            }
            this.appendXMLLineIndent(xml, indent + 1);
            xml.append("</Battings>\n");
        }
        
        if (this.bowlingOutput) {
        	
        	this.appendXMLLineIndent(xml, indent + 1);
            xml.append("<Bowlings>\n");
            List<BowlingInning> bowls = inn.getBowlInnings();
            if (bowls != null) {
                
                for (int i=0;i<bowls.size();i++) {
                    BowlingInning bowlinn = bowls.get(i);
                    
                    this.appendXMLLineIndent(xml, indent + 2);
                    xml.append("<BowlInn");
                    xml.append(this.appendXMLAttrib("id", (i+1), false));
                    xml.append(">\n"); 
                    
                    this.appendXMLLineIndent(xml, indent + 3);
                    xml.append("<Bowler");
                    xml.append(this.appendXMLAttrib("id", bowlinn.getBowler().getId(), false));
                    xml.append(this.appendXMLAttrib("name", bowlinn.getBowler().getTitleName(), true));
                    xml.append(this.appendXMLAttrib("shortname", bowlinn.getBowler().getShortName(), true));
                    xml.append(" />\n");
                    
                    this.appendXMLLineIndent(xml, indent + 3);
                    xml.append("<Stats");
                    xml.append(this.appendXMLAttrib("overs", bowlinn.getStatistics().getOvers(), false));
                    xml.append(this.appendXMLAttrib("maidnes", bowlinn.getStatistics().getMaidnes(), false));
                    xml.append(this.appendXMLAttrib("runs", bowlinn.getStatistics().getRuns(), false));
                    xml.append(this.appendXMLAttrib("wickets", bowlinn.getStatistics().getWickets(), false));
                    xml.append(this.appendXMLAttrib("nb", bowlinn.getStatistics().getNoballs(), false));
                    xml.append(this.appendXMLAttrib("wd", bowlinn.getStatistics().getWides(), false));
                    xml.append(" />\n");
                    
                    this.appendXMLLineIndent(xml, indent + 2);
                    xml.append("</BowlInn>\n");
                }
                
            }
            
            this.appendXMLLineIndent(xml, indent + 1);
            xml.append("</Bowlings>\n");
            
        }
        
        if (this.fallOfWicketOutput) {
        	
        	this.appendXMLLineIndent(xml, indent + 1);
            xml.append("<Wickets>\n");
            
            List<FallOfWicket> fows = inn.getFallWickets();
            if (fows != null) {
                
                for (int i=0;i<fows.size();i++) {
                    FallOfWicket fow = fows.get(i);
                    
                    this.appendXMLLineIndent(xml, indent + 2);
                    xml.append("<Wicket");
                    xml.append(this.appendXMLAttrib("no", fow.getWicket(), false));
                    xml.append(this.appendXMLAttrib("fallruns", fow.getFallOfRuns(), false));
                    xml.append(this.appendXMLAttrib("outbatsman", fow.getOutPlayer().getTitleName(), true));
                    if (fow.isRetiredHurt()) {
                        xml.append(this.appendXMLAttrib("retired", fow.isRetiredHurt(), false));
                    }
                    if (fow.getFallOfOver() != null) {
                        xml.append(this.appendXMLAttrib("fallover", fow.getFallOfOver(), false));
                    }
                    xml.append(" />\n");
                    
                }
                
            }
            this.appendXMLLineIndent(xml, indent + 1);
            xml.append("</Wickets>\n");
            
        }
        
        
        this.appendXMLLineIndent(xml, indent);
        xml.append("</Inning>\n");
        
        return xml;
    }
    
    private String appendXMLAttrib(String attrb, boolean value, boolean doencode) {
        return this.appendXMLAttrib(attrb, (value ? "true" : "false"), doencode);
    }
    private String appendXMLAttrib(String attrb, int value, boolean doencode) {
        return this.appendXMLAttrib(attrb, value + "", doencode);
    }
    private String appendXMLAttrib(String attrb, String value, boolean doencode) {
        if (doencode) {
            return " " + attrb + "=\"" + StringEscapeUtils.escapeXml(value) + "\"";
        } else {
            return " " + attrb + "=\"" + (value) + "\"";
        }
    }
    private void appendXMLLineIndent(StringBuilder xml, int indent) {
        for (int i=0;i<indent;i++) {
            xml.append('\t');
        }
    }
    
    public boolean isBattingOutput() {
		return battingOutput;
	}
    
    public void setFallOfWicketOutput(boolean fallOfWicketOutput) {
		this.fallOfWicketOutput = fallOfWicketOutput;
	}
    
    public void setBowlingOutput(boolean bowlingOutput) {
		this.bowlingOutput = bowlingOutput;
	}
    
    public void setBattingOutput(boolean battingOutput) {
		this.battingOutput = battingOutput;
	}
    
    public boolean isFallOfWicketOutput() {
		return fallOfWicketOutput;
	}
    
    public boolean isBowlingOutput() {
		return bowlingOutput;
	}
    
}
